home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / mkswap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-11  |  6.3 KB  |  300 lines

  1. /*
  2.  * mkswap.c - set up a linux swap device
  3.  *
  4.  * (C) 1991 Linus Torvalds. This file may be redistributed as per
  5.  * the Linux copyright.
  6.  *
  7.  * (C) 1996 Red Hat Software - Modified by Erik Troan for Red Hat Software 
  8.  *     still GPLed, of course
  9.  */
  10.  
  11. /*
  12.  * 20.12.91  -    time began. Got VM working yesterday by doing this by hand.
  13.  *
  14.  * Usuage: mkswap [-c] device [size-in-blocks]
  15.  *
  16.  *    -c for readablility checking (use it unless you are SURE!)
  17.  *
  18.  * The device may be a block device or a image of one, but this isn't
  19.  * enforced (but it's not much fun on a character device :-).
  20.  *
  21.  * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
  22.  * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
  23.  */
  24.  
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/stat.h>
  32. #include <unistd.h>
  33.  
  34. #include <linux/mm.h>
  35.  
  36. #include "devices.h"
  37. #include "install.h"
  38. #include "log.h"
  39. #include "mkswap.h"
  40. #include "newt.h"
  41. #include "windows.h"
  42.  
  43. #ifndef __linux__
  44. # define volatile
  45. #endif
  46.  
  47. #define TEST_BUFFER_PAGES 8
  48.  
  49. static int DEV = -1;
  50. static long PAGES = 0;
  51. static int check = 0;
  52. static int badpages = 0;
  53.  
  54. static long bit_test_and_set (unsigned int *addr, unsigned int nr)
  55. {
  56.     unsigned int r, m;
  57.  
  58.     addr += nr / (8 * sizeof(int));
  59.     r = *addr;
  60.     m = 1 << (nr & (8 * sizeof(int) - 1));
  61.     *addr = r | m;
  62.     return (r & m) != 0;
  63. }
  64.  
  65. static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
  66. {
  67.     unsigned int r, m;
  68.  
  69.     addr += nr / (8 * sizeof(int));
  70.     r = *addr;
  71.     m = 1 << (nr & (8 * sizeof(int) - 1));
  72.     *addr = r & ~m;
  73.     return (r & m) != 0;
  74. }
  75.  
  76. static int check_blocks(int * signature_page, char * file)
  77. {
  78.     unsigned int current_page;
  79.     int do_seek = 1;
  80.     static char buffer[PAGE_SIZE];
  81.     newtComponent form = NULL, scale = NULL;
  82.  
  83.     if (check) {
  84.         newtOpenWindow(10, 10, 60, 5, "Formatting");
  85.         
  86.         form = newtForm(NULL, NULL, 0);
  87.  
  88.         sprintf(buffer, "Formatting swap space on device %s...", file);
  89.         newtFormAddComponent(form, newtLabel(1, 1, buffer));
  90.         scale = newtScale(1, 3, 58, PAGES);
  91.         newtFormAddComponent(form, scale);
  92.         newtDrawForm(form);
  93.         newtRefresh();
  94.     }
  95.  
  96.     current_page = 0;
  97.     while (current_page < PAGES) {
  98.         if (!check) {
  99.             bit_test_and_set(signature_page,current_page++);
  100.             continue;
  101.         }
  102.  
  103.         newtScaleSet(scale, current_page);
  104.         newtRefresh();
  105.  
  106.         if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
  107.         current_page*PAGE_SIZE) {
  108.             logMessage("mkswap: seek failed in check_blocks");
  109.             return INST_ERROR;
  110.         }
  111.         if ((do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE)))) {
  112.             bit_test_and_clear(signature_page,current_page++);
  113.             badpages++;
  114.             continue;
  115.         }
  116.         bit_test_and_set(signature_page,current_page++);
  117.     }
  118.     if (badpages)
  119.         logMessage("\t%d bad page%s\n",badpages,(badpages>1)?"s":"");
  120.  
  121.     if (check) {
  122.         newtPopWindow();
  123.         newtFormDestroy(form);
  124.     }
  125.  
  126.     return 0;
  127. }
  128.  
  129. static long valid_offset (int fd, int offset)
  130. {
  131.     char ch;
  132.  
  133.     if (lseek (fd, offset, 0) < 0)
  134.         return 0;
  135.     if (read (fd, &ch, 1) < 1)
  136.         return 0;
  137.     return 1;
  138. }
  139.  
  140. static int count_blocks (int fd)
  141. {
  142.     int high, low;
  143.  
  144.     low = 0;
  145.     for (high = 1; valid_offset (fd, high); high *= 2)
  146.         low = high;
  147.     while (low < high - 1)
  148.     {
  149.         const int mid = (low + high) / 2;
  150.  
  151.         if (valid_offset (fd, mid))
  152.             low = mid;
  153.         else
  154.             high = mid;
  155.     }
  156.     valid_offset (fd, 0);
  157.     return (low + 1);
  158. }
  159.  
  160. static int get_size(const char  *file, long int * sizeptr)
  161. {
  162.     int    fd;
  163.     int    size;
  164.  
  165.     fd = open(file, O_RDWR);
  166.     if (fd < 0) {
  167.         logMessage("mkswap: failed to get size of device %s", file);
  168.         return INST_ERROR;
  169.     }
  170.     if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
  171.         close(fd);
  172.         *sizeptr = size * 512;
  173.         return 0;
  174.     }
  175.         
  176.     *sizeptr = count_blocks(fd);
  177.     close(fd);
  178.  
  179.     return 0;;
  180. }
  181.  
  182. int enableswap(char * device_name, int size, int checkBlocks) {
  183.     struct stat statbuf;
  184.     int goodpages;
  185.     int signature_page[PAGE_SIZE/sizeof(int)];
  186.     char devicefile[100];
  187.  
  188.     check = checkBlocks;
  189.  
  190.     if (testing) {
  191.         messageWindow("Testing", "I would make and enable swap on %s",
  192.               device_name);
  193.         return 0;
  194.     }
  195.  
  196.     memset(signature_page,0,PAGE_SIZE);
  197.  
  198.     if (*device_name == '/') {
  199.         strcpy(devicefile, device_name);
  200.     } else {
  201.         sprintf(devicefile, "/tmp/%s", device_name);
  202.         if (devMakeInode(device_name, devicefile)) {
  203.         return INST_ERROR;
  204.         }
  205.     }
  206.  
  207.     if (size)
  208.         PAGES = size;
  209.     else {
  210.         if (get_size(devicefile, &PAGES)) {
  211.             unlink(devicefile);
  212.             return INST_ERROR;
  213.         }
  214.  
  215.         PAGES = PAGES / PAGE_SIZE;
  216.     }
  217.  
  218.     if (PAGES<10) {
  219.         logMessage("mkswap: error: swap area needs to be at least "
  220.                 "%ldkB", 10 * PAGE_SIZE / 1024);
  221.         unlink(devicefile);
  222.         return INST_ERROR;
  223.     }
  224.  
  225.     if (PAGES > 8 * (PAGE_SIZE - 10)) {
  226.             PAGES = 8 * (PAGE_SIZE - 10);
  227.         logMessage("mkswap: warning: truncating %s swap to %ldkB",
  228.             device_name, PAGES * PAGE_SIZE / 1024);
  229.     }
  230.  
  231.     DEV = open(devicefile,O_RDWR);
  232.     if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
  233.         logMessage("mkswap: failed to open device: %s\n", device_name);
  234.         unlink(devicefile);
  235.         return INST_ERROR;
  236.     }
  237.     if (!S_ISBLK(statbuf.st_mode))
  238.         check=0;
  239.     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
  240.         logMessage("mkswap: will not try to make swapdevice on '%s'");
  241.         close(DEV);
  242.         unlink(devicefile);
  243.         return INST_ERROR;
  244.     }
  245.  
  246.     if (check_blocks(signature_page, device_name)) {
  247.         close(DEV);
  248.         unlink(devicefile);
  249.         newtPopWindow();
  250.         return INST_ERROR;
  251.     }
  252.  
  253.     if (!bit_test_and_clear(signature_page,0)) {
  254.         logMessage("mkswap: first page unreadable");
  255.         close(DEV);
  256.         unlink(devicefile);
  257.         newtPopWindow();
  258.         return INST_ERROR;
  259.     }
  260.  
  261.     goodpages = PAGES - badpages - 1;
  262.     if (goodpages <= 0) {
  263.         logMessage("mkswap: unable to set up swap-space: unreadable");
  264.         close(DEV);
  265.         unlink(devicefile);
  266.         newtPopWindow();
  267.         return INST_ERROR;
  268.     }
  269.  
  270.     logMessage("setting up swapspace, device = %s, size = %d bytes",
  271.         device_name, goodpages*PAGE_SIZE);
  272.     strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
  273.     if (lseek(DEV, 0, SEEK_SET)) {
  274.         logMessage("mkswap: unable to rewind swap-device");
  275.         close(DEV);
  276.         unlink(devicefile);
  277.         newtPopWindow();
  278.         return INST_ERROR;
  279.     }
  280.  
  281.     if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) {
  282.         logMessage("mkswap: unable to write signature page");
  283.         close(DEV);
  284.         unlink(devicefile);
  285.         newtPopWindow();
  286.         return INST_ERROR;
  287.     }
  288.  
  289.     close(DEV);
  290.  
  291.     if (swapon(devicefile)) {
  292.         logMessage("mkswap: swapon() failed: %s\n", strerror(errno));
  293.     }
  294.  
  295.     if (*device_name != '/') 
  296.         unlink(devicefile);
  297.  
  298.     return 0;
  299. }
  300.